﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Al_FrameWork;
using UnityEditor;
using UnityEngine;

namespace Editor
{
    /// <summary>
    /// AB打包
    /// </summary>
    public class ABPackEditor : UnityEditor.Editor
    {
        /// <summary>
        /// 场景本地资源路径
        /// </summary>
        private static string AssetBundleResPath = $"{Application.dataPath}/" + GameConfig.AssetBundlesFolderName;

        /// <summary>
        ///路径
        /// </summary>
        private static string AssetbundleOutPutPath =
            Path.Combine(Environment.CurrentDirectory, GameConfig.AssetBundlesFolderName);

        /// <summary>
        /// AB包里包含的assetbundle
        /// </summary>
        private static List<AssetBundleBuild> ABsBuildList = new List<AssetBundleBuild>();

        /// <summary>
        /// BuildAssetsBundleWindowsx64
        /// </summary>
        [MenuItem("打包工具/1=>打包上传资源(Windows[x64])", false, 2)]
        public static void BuildAssetsBundleWindowsx64()
        {
            BuildResources(BuildTarget.StandaloneWindows64);
        }


        /// <summary>
        /// BuildAssetsBundleAndroid
        /// </summary>
        [MenuItem("打包工具/2=>打包上传资源(Android)", false, 3)]
        public static void BuildAssetsBundleAndroid()
        {
            BuildResources(BuildTarget.Android);
        }

        /// <summary>
        /// BuildAssetsBundleIOS
        /// </summary>
        [MenuItem("打包工具/3=>打包上传资源(IOS)", false, 4)]
        public static void BuildAssetsBundleIOS()
        {
            BuildResources(BuildTarget.iOS);
        }


        // [MenuItem("打包工具/上传至web服务器目录")]
        public static void UploadWebServer(BuildTarget buildTarget)
        {
            List<string> dirs = new List<string>();
            ABIOTools.GetAllDirectorysInPath(AssetbundleOutPutPath, in dirs);
            //创建不存在的文件夹
            foreach (string dir in dirs)
            {
                string dirName = dir.Substring(AssetbundleOutPutPath.Length + 1);
                string dirPath = ABPackConfig.webBaseURL + dirName;
                if (!Directory.Exists(dirPath))
                {
                    Directory.CreateDirectory(dirPath);
                }
            }
            
            List<string> files = new List<string>();
            ABIOTools.GetFilesInPath(Path.Combine(AssetbundleOutPutPath, ABIOTools.GetPlatformName(buildTarget)),
                in files);
            StringBuilder sb = new StringBuilder();
            //拷贝前创建路径
            foreach (string file in files)
            {
                string filename = file.Substring(AssetbundleOutPutPath.Length + 1);
                File.Copy(file, ABPackConfig.webBaseURL + filename, true);
                GlobalFunctions.LOG("copy文件{0}=>{1}", file, ABPackConfig.webBaseURL + filename);
            }

            GlobalFunctions.LOG("======上传完成======");
        }

        /// <summary>
        /// 创建比对文件
        /// </summary>
        /// <param name="buildTarget"></param>
        public static void CreateCompareFile(BuildTarget buildTarget)
        {
            GlobalFunctions.LOG("{0}=======CreateCompareFile", ABIOTools.GetAssetBundleOutputPath(buildTarget));
            List<FileInfo> fileInfos =
                ABIOTools.GetFileInfos(ABIOTools.GetAssetBundleOutputPath(buildTarget));
            StringBuilder sb = new StringBuilder();
            foreach (FileInfo fileInfo_ in fileInfos)
            {
                if (!fileInfo_.Extension.Equals(ABPackConfig.filtermetasuffix) &&
                    !fileInfo_.Extension.Equals(ABPackConfig.filtermanifestsuffix))
                {
                    //相对路径
                    string localPath =
                        fileInfo_.FullName.Substring(ABIOTools.GetAssetBundleOutputPath(buildTarget).Length);
                    localPath = ABIOTools.FormatToUnityPath(localPath);
                    //文件大小
                    long size = fileInfo_.Length;
                    //文件md5码
                    string md5 = ABIOTools.GetFileMD5Code(fileInfo_.FullName);
                    string filename = fileInfo_.Name;
                    sb.AppendFormat("{0}{1}{2}{3}{4}{5}{6}\n", localPath, ABPackConfig.CommonMapPattern, md5,
                        ABPackConfig.CommonMapPattern, size, ABPackConfig.CommonMapPattern, filename);
                }
            }


            File.WriteAllText(ABIOTools.GetAssetBundleOutputPath(buildTarget) + "/ABCompareInfo.txt",
                sb.ToString());
            GlobalFunctions.LOG(sb.ToString());
            GlobalFunctions.LOG("======打包完毕======");
            AssetDatabase.Refresh();
        }

        /// <summary>
        /// BuildResources
        /// </summary>
        private static void BuildResources(BuildTarget buildTarget)
        {
            if (ABsBuildList.Count > 0)
            {
                GlobalFunctions.LOG("清理");
                ABsBuildList.Clear();
            }

            string outPath = ABIOTools.GetAssetBundleOutputPath(buildTarget);
            GlobalFunctions.LOG("BuildResources outPath= {0}", outPath);
            ABIOTools.CheckOrCreateDir(outPath);
            BuildAllLuaScripts();
            BuildAllScenes();
            BuildAllPrefabs();
            BuildAllTexturesAndTpsheet();
            BuildAB(buildTarget);
            CreateCompareFile(buildTarget);
            UploadWebServer(buildTarget);
            //刷新
            AssetDatabase.Refresh();
        }

        /// <summary>
        /// BuildAB
        /// </summary>
        /// <param name="buildTarget"></param>
        private static void BuildAB(BuildTarget buildTarget)
        {
            string outPath = ABIOTools.GetAssetBundleOutputPath(buildTarget);
            if (!Directory.Exists(outPath))
            {
                Directory.CreateDirectory(outPath);
            }
            else
            {
                Directory.Delete(outPath);
                Directory.CreateDirectory(outPath);
            }

            BuildPipeline.BuildAssetBundles(outPath, ABsBuildList.ToArray(), BuildAssetBundleOptions.None, buildTarget);
        }


        /// <summary>
        /// 打包预制件
        /// </summary>
        /// <param name="buildTarget"></param>
        private static void BuildAllPrefabs()
        {
            string[] prefabFiles =
                Directory.GetFiles(AssetBundleResPath + "/Prefabs/", "*.prefab", SearchOption.AllDirectories);
            List<string> assetNameList = new List<string>();
            foreach (string file in prefabFiles)
            {
                assetNameList.Add(file.Substring(file.IndexOf("Assets/")));
            }

            AssetBundleBuild buildInfo = new AssetBundleBuild();
            buildInfo.assetBundleName = "prefabs" + GameConfig.AssetBundleSuffix;
            buildInfo.assetNames = assetNameList.ToArray();
            ABsBuildList.Add(buildInfo);
            EditorUtility.ClearProgressBar();
        }
        
        /// <summary>
        /// 打包场景资源
        /// </summary>
        private static void BuildAllScenes()
        {
            string[] sceneFiles =
                Directory.GetFiles(AssetBundleResPath + $"/Scenes/", $"*.unity", SearchOption.AllDirectories);
            List<string> assetNamesList = new List<string>();
            //需要打包的场景
            foreach (string file in sceneFiles)
            {
                //设置bundle名，和多少资源打在同一个Bundle内
                assetNamesList.Add(file.Substring(file.IndexOf("Assets/")));
            }

            AssetBundleBuild buildPacket = new AssetBundleBuild();
            buildPacket.assetBundleName = "scenes" + GameConfig.AssetBundleSuffix;
            buildPacket.assetNames = assetNamesList.ToArray();
            ABsBuildList.Add(buildPacket);
        }

        /// <summary>
        /// 打包所有lua脚本
        /// </summary>
        private static void BuildAllLuaScripts()
        {
            string path = Path.Combine(AssetBundleResPath, GameConfig.LuaScriptsFolder);
            string[] luaFiles = Directory.GetFiles(Path.Combine(AssetBundleResPath, GameConfig.LuaScriptsFolder),
                "*.lua.txt",
                SearchOption.AllDirectories);
            List<string> assetNameList = new List<string>();
            foreach (string file in luaFiles)
            {
                assetNameList.Add(file.Substring(file.IndexOf("Assets/")));
            }

            AssetBundleBuild buildPacket = new AssetBundleBuild();
            buildPacket.assetBundleName = "luascripts" + GameConfig.AssetBundleSuffix;
            buildPacket.assetNames = assetNameList.ToArray();
            ABsBuildList.Add(buildPacket);
        }


        /// <summary>
        /// 打包所有的UI纹理
        /// </summary>
        /// <param name="buildTarget"></param>
        private static void BuildAllTexturesAndTpsheet()
        {
            string[] textureFiles =
                Directory.GetFiles(AssetBundleResPath + "/Textures/", "*.png", SearchOption.AllDirectories);
            List<string> assetNamesList = new List<string>();
            foreach (string file in textureFiles)
            {
                assetNamesList.Add(file.Substring(file.IndexOf("Assets/")));
            }

            AssetBundleBuild buildInfo = new AssetBundleBuild();
            buildInfo.assetBundleName = "textures" + GameConfig.AssetBundleSuffix;
            buildInfo.assetNames = assetNamesList.ToArray();
            ABsBuildList.Add(buildInfo);
            EditorUtility.ClearProgressBar();
        }
    }
}